package com.xukun.changgou.service.sys.config.interceptor;

import com.alibaba.fastjson.JSON;
import com.xukun.changgou.common.annotation.BaseAccess;
import com.xukun.changgou.common.constants.CommonConstant;
import com.xukun.changgou.common.response.ResponseEnum;
import com.xukun.changgou.common.response.exception.BaseException;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @Author xukun
 * @Date 2021-06-04 15:27
 * @Description 自定义安全拦截器，处理请求的接口的的权限
 */
public class BaseSecurityInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //在网关处已获取过权限，此处直接获取即可，如果获取不到，说明没有从网关处进行请求，进行拦截
        String authority = request.getHeader(CommonConstant.AUTH_HEADER);
        if(ObjectUtils.isEmpty(authority)){
            throw new BaseException(ResponseEnum.DENY_ACCESS);
        }
        List<String> authorities = JSON.parseObject(authority, List.class);

        //处理权限问题
        if (!checkAccess(handler, authorities)) {
            throw new BaseException(ResponseEnum.NO_ACCESS);
        }
        return true;
    }

    /**
     * 检查权限
     *
     * @param handler
     * @param authorities 当前用户所拥有的权限列表
     * @return 有权限返回true
     */
    private boolean checkAccess(Object handler, List<String> authorities) {
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            BaseAccess annotation = method.getAnnotation(BaseAccess.class);
            if (ObjectUtils.isNotEmpty(annotation)) {
                String[] requireList = annotation.value();
                boolean requireAll = annotation.requireAll();
                if (requireAll) {
                    return andAccess(requireList, authorities);
                } else {
                    return orAccess(requireList, authorities);
                }
            }
        }
        return true;
    }

    /**
     * 和的关系
     *
     * @param requireList 要求的权限列表
     * @param authorities 拥有的权限列表
     * @return 满足权限和的关系返回true
     */
    private boolean andAccess(String[] requireList, List<String> authorities) {
        for (String require : requireList) {
            if (!authorities.contains(require)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 或的关系
     *
     * @param requireList 要求的权限列表
     * @param authorities 拥有的权限列表
     * @return 满足权限或的关系返回true
     */
    private boolean orAccess(String[] requireList, List<String> authorities) {
        for (String require : requireList) {
            if (authorities.contains(require)) {
                return true;
            }
        }
        return false;
    }
}
